package com.study.tx.annotation.service;

import com.study.tx.common.dao.OrderItemDao;
import com.study.tx.common.entity.Order;
import com.study.tx.common.entity.OrderItem;
import com.study.tx.common.service.OrderItemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.*;

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * 订单项接口的实现
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2021年02月02日
 */
@Slf4j
@Service("annotationOrderItemService")
public class AnnotationOrderItemServiceImpl implements OrderItemService {
    @Resource
    private OrderItemDao annotationOrderItemDao;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private PlatformTransactionManager transactionManager;
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    private OrderItem buildOrderItem(Order order, Long productId) {
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(order.getOrderId());
        orderItem.setUserId(order.getUserId());
        orderItem.setProductId(productId);
        orderItem.setProductName("商品名称-" + productId);
        orderItem.setProductPrice(BigDecimal.ONE);
        orderItem.setPurchaseCount(10);
        orderItem.setPayMoney(BigDecimal.TEN);
        return orderItem;
    }

    @Override
    public Integer truncateOrderItem() {
        int truncateOrderItem = annotationOrderItemDao.truncateOrderItem();
        log.info("清空 t_order_item 表结果：{}", truncateOrderItem);
        return truncateOrderItem;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public Integer insert(Order order, Long productId) {
        OrderItem orderItem = this.buildOrderItem(order, productId);
        /*if (true) {
            throw new RuntimeException("操作 t_order_item 之前抛出了异常！");
        }*/
        int result = annotationOrderItemDao.insert(orderItem);
        System.out.println("操作 t_order_item 结果：" + result);
        /*if (true) {
            throw new RuntimeException("操作 t_order_item 之后抛出了异常！");
        }*/
        // 发送消息到 MQ
        /*TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void beforeCommit(boolean readOnly) {
                log.info("调用了 beforeCommit() 方法，readOnly={}，参数：{}", readOnly, JSON.toJSONString(orderItem));
            }

            @Override
            public void afterCommit() {
                // 当数据成功保存到数据库中并且事务提交了，就发送消息到 MQ 中
                log.info("调用了 afterCommit() 方法，参数：{}", JSON.toJSONString(orderItem));
            }

            @Override
            public void beforeCompletion() {
                log.info("调用了 beforeCompletion() 方法，参数：{}", JSON.toJSONString(orderItem));
            }

            @Override
            public void afterCompletion(int status) {
                log.info("调用了 afterCompletion() 方法，status={}，参数：{}", status, JSON.toJSONString(orderItem));
            }
        });*/
        // 发布一个自定义的事件
        /*applicationEventPublisher.publishEvent(new MyOrderItemTransactionEvent("操作 t_order_item 的事务事件，请事务提交后执行我~~~", orderItem));
        if (productId == null) {
            // 如果代码未发生异常，由于业务不满足某条件而需要回滚时，有两种解决方法：抛出自定义异常(常用)、通过编程代码回滚(不常用)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }*/
        return result;
    }

    @Override
    public void transactionTemplateWithoutResult(Order order, Long productId) {
        transactionTemplate.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    // 业务代码
                    OrderItem orderItem = buildOrderItem(order, productId);
                    int result4OrderItem = annotationOrderItemDao.insert(orderItem);
                    System.out.println("操作 t_order_item 结果：" + result4OrderItem);
                } catch (Exception e) {
                    // 回滚
                    transactionStatus.setRollbackOnly();
                }
            }
        });
    }

    @Override
    public Integer transactionTemplateWithResult(Order order, Long productId) {
        transactionTemplate.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
        Integer result = transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    // 业务代码
                    OrderItem orderItem = buildOrderItem(order, productId);
                    int result4OrderItem = annotationOrderItemDao.insert(orderItem);
                    System.out.println("操作 t_order_item 结果：" + result4OrderItem);
                    return result4OrderItem;
                } catch (Exception e) {
                    // 回滚
                    transactionStatus.setRollbackOnly();
                    return null;
                }
            }
        });
        return result;
    }

    @Override
    public void transactionManagerWithoutResult(Order order, Long productId) {
        // 定义事务属性
        DefaultTransactionDefinition transDef = new DefaultTransactionDefinition();
        // 设置传播行为属性
        transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
        // 获得事务状态
        TransactionStatus status = transactionManager.getTransaction(transDef);
        try {
            // 业务代码
            OrderItem orderItem = this.buildOrderItem(order, productId);
            int result4OrderItem = annotationOrderItemDao.insert(orderItem);
            System.out.println("操作 t_order_item 结果：" + result4OrderItem);
            // 提交
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滚
            transactionManager.rollback(status);
        }
    }

    @Override
    public Integer transactionManagerWithResult(Order order, Long productId) {
        // 定义事务属性
        DefaultTransactionDefinition transDef = new DefaultTransactionDefinition();
        // 设置传播行为属性
        transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
        // 获得事务状态
        TransactionStatus status = transactionManager.getTransaction(transDef);
        try {
            // 业务代码
            OrderItem orderItem = this.buildOrderItem(order, productId);
            int result4OrderItem = annotationOrderItemDao.insert(orderItem);
            System.out.println("操作 t_order_item 结果：" + result4OrderItem);
            // 提交
            transactionManager.commit(status);
            return result4OrderItem;
        } catch (Exception e) {
            // 回滚
            transactionManager.rollback(status);
            return null;
        }
    }
}
